/**
 * @file ThreadPool.h
 * @brief 线程池类的声明
 * 
 * 提供了一个高性能的线程池实现，特性包括：
 * 1. 基于任务队列的动态调度
 * 2. 支持异步任务提交和结果获取
 * 3. 自动线程生命周期管理
 * 4. 线程安全的任务分发
 * 5. 支持可变参数任务提交
 */
#pragma once
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <future>

class ThreadPool
{
public:
    /**
     * @brief 构造函数
     * @param threads 线程池中的工作线程数量
     * 
     * 创建指定数量的工作线程并初始化线程池：
     * 1. 分配线程资源
     * 2. 初始化同步原语
     * 3. 启动工作线程
     */
    explicit ThreadPool(size_t threads);

    /**
     * @brief 析构函数
     * 
     * 清理线程池资源：
     * 1. 等待所有任务完成
     * 2. 通知所有线程退出
     * 3. 释放线程资源
     */
    ~ThreadPool();

    /**
     * @brief 向线程池提交任务
     * @tparam F 任务函数类型
     * @tparam Args 任务参数类型包
     * @param f 任务函数
     * @param args 任务参数
     * @return std::future对象，用于获取任务执行结果
     * 
     * 任务提交流程：
     * 1. 包装任务函数和参数
     * 2. 创建promise-future对
     * 3. 将任务添加到队列
     * 4. 通知工作线程处理新任务
     */
    template<class F, class... Args>
    auto submit(F&& f, Args&&... args) 
        -> std::future<typename std::result_of<F(Args...)>::type>;

    /**
     * @brief 获取线程池中的线程数量
     * @return 返回工作线程数量
     */
    size_t threadCount() const { return workers.size(); }

private:
    std::vector<std::thread> workers;    ///< 工作线程容器，存储所有线程对象
    std::queue<std::function<void()>> tasks;  ///< 任务队列，存储待执行的任务
    
    std::mutex queue_mutex;              ///< 任务队列互斥锁，保护任务队列的线程安全访问
    std::condition_variable condition;    ///< 条件变量，用于线程同步和任务通知
    bool stop;                           ///< 停止标志，用于通知线程池关闭
};

/**
 * @brief 任务提交模板函数的实现
 * 
 * 使用完美转发和可变参数模板实现任务提交：
 * 1. 将任务函数和参数打包成可调用对象
 * 2. 创建共享状态
 * 3. 将任务封装并加入队列
 * 4. 返回future对象
 */
template<class F, class... Args>
auto ThreadPool::submit(F&& f, Args&&... args) 
    -> std::future<typename std::result_of<F(Args...)>::type>
{
    using return_type = typename std::result_of<F(Args...)>::type;

    auto task = std::make_shared<std::packaged_task<return_type()>>(
        std::bind(std::forward<F>(f), std::forward<Args>(args)...)
    );
    
    std::future<return_type> res = task->get_future();
    {
        std::unique_lock<std::mutex> lock(queue_mutex);
        if(stop)
            throw std::runtime_error("提交任务到已停止的线程池");
        
        tasks.emplace([task](){ (*task)(); });
    }
    condition.notify_one();
    return res;
}